りおんクロニクル


C# × API連携(HttpClient / Refit)|RESTクライアント設計の実務ガイド【2026年版】

Home【2026年版】C# / .NET入門と実践ガイド|基礎・業務アプリ開発・SQLite連携まで体系的に解説

業務アプリで外部サービスと連携する場合、 REST API × JSON が今の標準です。 C#では HttpClient を素で使う方法と、 インターフェイス駆動で書ける Refit がよく使われます。

この記事でわかること
・HttpClientの正しい使い方(DI・タイムアウト・JSON)
・GET / POST / PUT / DELETE の基本
・Refitによるインターフェイス駆動のAPIクライアント
・エラー処理・リトライ・タイムアウト設計
・業務アプリ向けのAPIクライアント設計パターン

1. HttpClient と Refit の位置づけ

項目HttpClientRefit
特徴標準・低レベル・柔軟インターフェイス駆動・宣言的
コード量多い少ない
制御性高い(何でもできる)高いが抽象化される
向き細かい制御・特殊ケース典型的なREST APIクライアント

まずはHttpClientを理解 → その上でRefitを使う という順番が一番しっくりきます。

2. HttpClientの正しい使い方(DI前提)

HttpClientは「毎回 new して Dispose」するとポート枯渇・パフォーマンス劣化の原因になります。 HttpClientFactory(DI)で管理するのが現代の標準です。

■ 2-1. DI登録(.NET 6 以降)

builder.Services.AddHttpClient("MyApi", client =>
{
    client.BaseAddress = new Uri("https://api.example.com/");
    client.Timeout = TimeSpan.FromSeconds(30);
});

■ 2-2. コンストラクタインジェクションで受け取る

public class MyApiClient
{
    private readonly HttpClient _http;

    public MyApiClient(IHttpClientFactory factory)
    {
        _http = factory.CreateClient("MyApi");
    }
}

3. HttpClientでの基本的なAPI呼び出し

■ 3-1. GET(JSON取得)

public record UserDto(int Id, string Name);

public async Task<UserDto?> GetUserAsync(int id)
{
    var res = await _http.GetAsync($"/users/{id}");
    if (!res.IsSuccessStatusCode)
        return null;

    var json = await res.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<UserDto>(json);
}

■ 3-2. POST(JSON送信)

public record CreateUserRequest(string Name);
public record CreateUserResponse(int Id, string Name);

public async Task<CreateUserResponse?> CreateUserAsync(string name)
{
    var req = new CreateUserRequest(name);
    var json = JsonSerializer.Serialize(req);
    using var content = new StringContent(json, Encoding.UTF8, "application/json");

    var res = await _http.PostAsync("/users", content);
    if (!res.IsSuccessStatusCode)
        return null;

    var resJson = await res.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<CreateUserResponse>(resJson);
}

■ 3-3. PUT / DELETE

public Task<HttpResponseMessage> UpdateUserAsync(int id, CreateUserRequest req)
{
    var json = JsonSerializer.Serialize(req);
    using var content = new StringContent(json, Encoding.UTF8, "application/json");
    return _http.PutAsync($"/users/{id}", content);
}

public Task<HttpResponseMessage> DeleteUserAsync(int id)
{
    return _http.DeleteAsync($"/users/{id}");
}

4. エラー処理・タイムアウト・リトライ

業務アプリでは、ネットワークエラー・タイムアウト・5xx をどう扱うかが重要です。

■ 4-1. ステータスコードのチェック

var res = await _http.GetAsync("/users/1");
if (res.StatusCode == HttpStatusCode.NotFound)
{
    // 見つからない → null扱いなど
}
res.EnsureSuccessStatusCode(); // 2xx以外なら例外

■ 4-2. タイムアウト

_http.Timeout = TimeSpan.FromSeconds(10);

「いつまでも待つ」はNG。業務要件に合わせて秒数を決めます。

■ 4-3. Pollyでリトライ(よくあるパターン)

builder.Services.AddHttpClient("MyApi", client =>
{
    client.BaseAddress = new Uri("https://api.example.com/");
})
.AddTransientHttpErrorPolicy(p =>
    p.WaitAndRetryAsync(3, retry => TimeSpan.FromSeconds(Math.Pow(2, retry))));

一時的なネットワークエラーに対して、自動リトライが効くようになります。

5. Refitでインターフェイス駆動のAPIクライアント

Refitは、「インターフェイスに属性を書くと、実装を自動生成してくれる」 ライブラリです。 Retrofit(Android)のC#版のようなイメージです。

■ 5-1. インターフェイス定義

using Refit;

public record UserDto(int Id, string Name);
public record CreateUserRequest(string Name);
public record CreateUserResponse(int Id, string Name);

public interface IMyApi
{
    [Get("/users/{id}")]
    Task<UserDto> GetUserAsync(int id);

    [Post("/users")]
    Task<CreateUserResponse> CreateUserAsync([Body] CreateUserRequest request);

    [Put("/users/{id}")]
    Task UpdateUserAsync(int id, [Body] CreateUserRequest request);

    [Delete("/users/{id}")]
    Task DeleteUserAsync(int id);
}

■ 5-2. クライアント生成

var api = RestService.For<IMyApi>("https://api.example.com");

var user = await api.GetUserAsync(1);

■ 5-3. DI登録(HttpClientFactory連携)

builder.Services
    .AddRefitClient<IMyApi>()
    .ConfigureHttpClient(c =>
    {
        c.BaseAddress = new Uri("https://api.example.com");
        c.Timeout = TimeSpan.FromSeconds(30);
    });

あとはコンストラクタで IMyApi を受け取るだけで使えます。

6. 認証付きAPI(Bearerトークンなど)

■ 6-1. HttpClientでAuthorizationヘッダー

_http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", accessToken);

■ 6-2. Refit + HttpClientHandler

builder.Services
    .AddRefitClient<IMyApi>()
    .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.example.com"))
    .AddHttpMessageHandler(() => new AuthHandler());

public class AuthHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // ここでトークン取得・更新など
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "token");
        return await base.SendAsync(request, cancellationToken);
    }
}

共通の認証ロジックをハンドラに閉じ込められます。

7. 業務アプリ向けAPIクライアント設計パターン

8. UIとの連携(WPF / Blazor / WinForms)

UIから直接HttpClientを叩くのではなく、 「アプリケーションサービス → APIクライアント」 の順で呼ぶと設計がきれいになります。

■ 8-1. アプリケーションサービス例

public interface IUserService
{
    Task<UserDto?> GetUserAsync(int id);
}

public class UserService : IUserService
{
    private readonly IMyApi _api;

    public UserService(IMyApi api) => _api = api;

    public Task<UserDto?> GetUserAsync(int id)
        => _api.GetUserAsync(id);
}

ViewModel / UI は IUserService だけを知っていればよくなります。

9. 業務アプリ向けベストプラクティス

まとめ:HttpClientを理解したうえでRefitを使うと“API連携が一気に楽になる”

「とりあえずHttpClientで叩く」 から一歩進んで、 「設計されたAPIクライアント」 を持つことで、 業務アプリの保守性と信頼性は大きく向上します。 この記事をベースに、あなたのプロジェクトに合ったAPI連携の形を設計してみてください。

前のページ  次のページ